package com.vision.sales.debitmemo.cl.u;

import static com.vision.sales.cl.SalesServices.debitMemoSvc;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

import com.allen_sauer.gwt.log.client.Log;
import com.google.gwt.core.client.GWT;
import com.google.gwt.editor.client.Editor;
import com.google.gwt.editor.client.SimpleBeanEditorDriver;
import com.google.gwt.event.logical.shared.SelectionEvent;
import com.google.gwt.i18n.client.NumberFormat;
import com.google.gwt.safehtml.shared.SafeHtml;
import com.google.gwt.text.shared.AbstractSafeHtmlRenderer;
import com.google.gwt.uibinder.client.UiBinder;
import com.google.gwt.uibinder.client.UiFactory;
import com.google.gwt.uibinder.client.UiField;
import com.google.gwt.uibinder.client.UiHandler;
import com.google.gwt.user.client.ui.IsWidget;
import com.google.gwt.user.client.ui.Widget;
import com.sencha.gxt.widget.core.client.Window;
import com.sencha.gxt.widget.core.client.button.TextButton;
import com.sencha.gxt.widget.core.client.container.VerticalLayoutContainer;
import com.sencha.gxt.widget.core.client.event.SelectEvent;
import com.sencha.gxt.widget.core.client.form.DateField;
import com.sencha.gxt.widget.core.client.form.NumberField;
import com.sencha.gxt.widget.core.client.form.NumberPropertyEditor;
import com.sencha.gxt.widget.core.client.form.SimpleComboBox;
import com.sencha.gxt.widget.core.client.form.TextArea;
import com.sencha.gxt.widget.core.client.form.TextField;
import com.sencha.gxt.widget.core.client.form.validator.MaxLengthValidator;
import com.vision.core.cl.BaseModule;
import com.vision.core.cl.Callback;
import com.vision.core.cl.ui.Notifications;
import com.vision.core.cl.ui.UI;
import com.vision.core.cl.ui.component.CompanyComboBox;
import com.vision.core.cl.ui.component.EnumComboBox;
import com.vision.core.cm.db.data.Company;
import com.vision.sales.cl.SalesServices;
import com.vision.sales.cl.event.DebitMemoCreatedEvent;
import com.vision.sales.cl.resource.SalesResources;
import com.vision.sales.cl.ui.component.CustomerComboBox;
import com.vision.sales.cl.ui.component.SalesInvoiceComboBox;
import com.vision.sales.cl.ui.component.SalesInvoiceComboBox.Templates;
import com.vision.sales.cm.data.DataUtils;
import com.vision.sales.cm.data.DebitMemoType;
import com.vision.sales.cm.db.data.Customer;
import com.vision.sales.cm.db.data.DebitMemo;
import com.vision.sales.cm.db.data.DebitMemo.FieldSpecs;
import com.vision.sales.cm.db.data.SalesInvoice;

/**
 * 
 * @author Mark
 *
 */
public class CreateDebitMemoWindow implements IsWidget, Editor<DebitMemo> {
	
	interface Binder extends UiBinder<Widget, CreateDebitMemoWindow> { }
	
	private static final Binder binder = GWT.create(Binder.class);
	
	@UiField Window window;
	@UiField VerticalLayoutContainer mainPanel;

	@UiField CompanyComboBox company;
	@UiField CustomerComboBox customer;
	@UiField TextField debitMemoNo;
	@UiField DateField date;
	@UiField SimpleComboBox<DebitMemoType> type;
	@UiField NumberField<Double> amount;
	@UiField(provided = true) SalesInvoiceComboBox salesInvoice;
	@UiField TextArea remarks;
	
	@Ignore @UiField TextButton saveBtn;
	@Ignore @UiField TextButton cancelBtn;
	
	@UiField(provided = true) NumberFormat numberFormat = UI.amountFormat();
	@UiField(provided = true) NumberPropertyEditor<Double> doublePropertyEditor = UI.doubleEditor();
	
	interface DebitMemoDriver extends SimpleBeanEditorDriver<DebitMemo, CreateDebitMemoWindow> { }
	
	private DebitMemoDriver driver = GWT.create(DebitMemoDriver.class); // Used to bind the grid to the form editor
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@Override
	public Widget asWidget() {
		salesInvoice = initializeSalesInvoiceCombo();
		
		window = (Window) binder.createAndBindUi(this);
		window.getHeader().setIcon(SalesResources.INSTANCE.debitMemos());
		
		date.setPropertyEditor(UI.datePropertyEditor());
		date.setValue(new Date());
		
		driver.initialize(this);
		driver.edit(new DebitMemo(new Timestamp(System.currentTimeMillis())));
		
		debitMemoNo.addValidator(new MaxLengthValidator(FieldSpecs.DM_NO_MAX));
		remarks.addValidator(new MaxLengthValidator(FieldSpecs.REMARKS_MAX));
		
		loadData();
		
		return window;
	}
	
	// UiFactory Methods %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	@Ignore
	@UiFactory
	SimpleComboBox<DebitMemoType> initializeDebitMemoTypeCombo() {
		return new EnumComboBox<DebitMemoType>(DebitMemoType.values());
	}
	
	@Ignore
	SalesInvoiceComboBox initializeSalesInvoiceCombo() {
		SalesInvoiceComboBox combo = new SalesInvoiceComboBox(new AbstractSafeHtmlRenderer<SalesInvoice>() {
			@Override
			public SafeHtml render(SalesInvoice invoice) {
				String date = UI.basicDateFormat(invoice.getDate());
				String gross = UI.AMOUNT_FORMAT.format(invoice.getGrossSales());
				String balance = UI.AMOUNT_FORMAT.format(invoice.getBalance());
				return Templates.INSTANCE.invoice(date, invoice.getGroupAndNo(), gross, balance);
			}
		});
		return combo;
	}
	
	// Logic %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

	public void loadData() {
		Log.debug("Loading companies, customers, sales invoices, for dropdown...");

		company.loadCompanies();
		customer.loadCustomers();
	}
	
	@UiHandler("company")
	void companyChanged(SelectionEvent<Company> e) {
		Company selectedCompany = e.getSelectedItem();
		Customer selectedCustomer = customer.getCurrentValue();
		if (selectedCustomer == null || selectedCompany == null)
			return;
		
		loadSalesInvoicesForDebitMemo(selectedCompany, selectedCustomer);
	}
	
	@UiHandler("customer")
	void customerChanged(SelectionEvent<Customer> e) {
		Customer selectedCustomer = e.getSelectedItem();
		Company selectedCompany = company.getCurrentValue();
		if (selectedCustomer == null || selectedCompany == null)
			return;
		
		loadSalesInvoicesForDebitMemo(selectedCompany, selectedCustomer);
	}
	
	@UiHandler("saveBtn")
	void saveClicked(SelectEvent e) {
		DebitMemo memo = driver.flush();
		if (driver.hasErrors())
			return;
		
		String message = DataUtils.checkDebitMemo(memo);
		if (message != null) {
			Notifications.info(message);
			return;
		}
		
		UI.mask(window, "Creating debit memo...");
		debitMemoSvc().create(memo, new Callback<DebitMemo>(window) {
			@Override
			protected void handleSuccess(DebitMemo result) {
				window.hide(saveBtn);
				BaseModule.fireEvent(new DebitMemoCreatedEvent(result));
			}
		});
	}
	
	@UiHandler("cancelBtn")
	void cancelClicked(SelectEvent e) {
		window.hide(cancelBtn);
	}
	
	// %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
	
	private void loadSalesInvoicesForDebitMemo(Company company, Customer customer) {
		salesInvoice.getStore().clear();
		salesInvoice.setValue(null);
		
		UI.mask(salesInvoice, "Loading sales invoices...");
		SalesServices.salesInvoiceSvc().getSalesInvoicesForCollection(company, customer, new Callback<List<SalesInvoice>>(salesInvoice) {
			@Override
			protected void handleSuccess(List<SalesInvoice> result) {
				salesInvoice.getStore().addAll(result);
			}
		});
	}
	
}
